package com.ruoyi.demowechatpay.controller;

import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.function.constant.BusinessConstants;
import com.ruoyi.function.domain.Orders;
import com.ruoyi.function.domain.SysTopUp;
import com.ruoyi.function.mapper.OrdersMapper;
import com.ruoyi.function.service.ISysTopUpService;
import com.ruoyi.function.service.IUserFlowingService;
import com.ruoyi.message.controller.NoticeController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 微信支付回调
 */
@Slf4j
@RestController
@RequestMapping("/wxpay/notify")
public class WxPayNotifyController {

    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private ISysTopUpService sysTopUpService;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private NoticeController noticeController;
    @Autowired
    private IUserFlowingService userFlowingService;

    /**
     * 支付回调 - 正确的方法
     */
    @PostMapping("/payment")
    public AjaxResult paymentNotify(@RequestBody String notifyData,
                                @RequestHeader("Wechatpay-Signature") String signature,
                                @RequestHeader("Wechatpay-Nonce") String nonce,
                                @RequestHeader("Wechatpay-Serial") String serial,
                                @RequestHeader("Wechatpay-Timestamp") String timestamp) {
        try {
            log.info("支付回调notifyData{}，signature{}，nonce{},serial{},timestamp{}",notifyData,signature,nonce,serial,timestamp);
            SignatureHeader header = new SignatureHeader();
            header.setSignature(signature);
            header.setNonce(nonce);
            header.setSerial(serial);
            header.setTimeStamp(timestamp);

            WxPayNotifyV3Result result = wxPayService.parseOrderNotifyV3Result(notifyData, header);
            WxPayNotifyV3Result.DecryptNotifyResult notifyResult = result.getResult();

            // 处理业务逻辑
            String outTradeNo = notifyResult.getOutTradeNo();
            String transactionId = notifyResult.getTransactionId();
            String tradeState = notifyResult.getTradeState();

            if ("SUCCESS".equals(tradeState)) {
                // 支付成功处理
                // TODO: 更新订单状态等业务逻辑
                SysTopUp sysTopUp = sysTopUpService.selectSysTopUpByTransactionId(outTradeNo);
                if (StringUtils.isNull(sysTopUp)){
                    throw new RuntimeException(String.format("%s订单存在", outTradeNo));
                }

                String orderJson = sysTopUp.getOrderJson();
                Orders orders = ordersMapper.selectOrdersByOrderId(Long.parseLong(orderJson));
                //修改订单
                // "merge' 是不是合并订单
                if ("merge".equals(sysTopUp.getOrderType()) ){
                    upOrders(orders,1);
                }else {
                    if ("0".equals(orders.getType())){
                        orders.setOrderStatus("1");
                    }else if ("1".equals(orders.getType())){
                        orders.setOrderStatus("5");
                        userFlowingService.addAmount(orders.getOrdersUser(), orders.getTotalAmount(), BusinessConstants.dict.fee_type_1, orders.getReceivingType(), orders.getUserId());
                    }

                    orders.setPaymentTime(new Date());
                    ordersMapper.updateOrders(orders);
                    // 发送消息
                    try {
                        noticeController.sendMessage(orders.getOrdersUser() + "", orders.getReceivingType(), BusinessConstants.message_1);

                    }catch (Exception e){
                        log.error("支付回调发送消息失败", e);
                    }
                }

                // 修改支付
                sysTopUp.setStatus("2");
                sysTopUpService.updateSysTopUp(sysTopUp);


            }

            // 返回成功响应
            log.info("{}: 回调成功", transactionId);
            return AjaxResult.success("回调成功");
        } catch (Exception e) {
            // 记录错误日志
            log.error(e.getMessage(), e);
            throw new RuntimeException("处理失败");
        }
    }

    private void upOrders(Orders orders,int orderStatus) {
        // 1:判断是否为额外订单
        List<Orders> objects = new ArrayList<>();
        objects.add(orders);
        if ("0".equals(orders.getType())){
            //根据定查询子订单
            List<Orders> list=    ordersMapper.selectOrdersByParentOrderType(orders.getOrderId());
            objects.addAll(list);
        }
        for (Orders orders1 : objects) {
            orders1.setOrderStatus("1");
            orders1.setPaymentTime(new Date());
            ordersMapper.updateOrders(orders1);
            try {
                noticeController.sendMessage(orders1.getOrdersUser() + "", orders1.getReceivingType(), BusinessConstants.message_1);

            }catch (Exception e){
                log.error("支付回调发送消息失败", e);
            }
        }

    }

    /**
     * 退款回调 - 正确的方法
     */
    @PostMapping("/refund")
    public AjaxResult refundNotify(@RequestBody String notifyData,
                               @RequestHeader("Wechatpay-Signature") String signature,
                               @RequestHeader("Wechatpay-Nonce") String nonce,
                               @RequestHeader("Wechatpay-Serial") String serial,
                               @RequestHeader("Wechatpay-Timestamp") String timestamp) {
        try {
            //打印所有参数
            log.info("退款回调notifyData{}，signature{}，nonce{},serial{},timestamp{}",notifyData,signature,nonce,serial,timestamp);

            SignatureHeader header = new SignatureHeader();
            header.setSignature(signature);
            header.setNonce(nonce);
            header.setSerial(serial);
            header.setTimeStamp(timestamp);

            WxPayRefundNotifyV3Result result = wxPayService.parseRefundNotifyV3Result(notifyData, header);
            WxPayRefundNotifyV3Result.DecryptNotifyResult notifyResult = result.getResult();

            // 处理业务逻辑
            String outTradeNo = notifyResult.getOutRefundNo();
            String refundStatus = notifyResult.getRefundStatus();

            if ("SUCCESS".equals(refundStatus)) {
                // 退款成功处理
                // TODO: 更新退款状态等业务逻辑
                SysTopUp sysTopUp = sysTopUpService.selectSysTopUpByTransactionId(outTradeNo);
                if (StringUtils.isNull(sysTopUp)){
                    throw new RuntimeException(String.format("%s订单存在", outTradeNo));

                }
                String orderJson = sysTopUp.getOrderJson();
                Orders orders = ordersMapper.selectOrdersByOrderId(Long.parseLong(orderJson));
                //修改订单
                List<Orders> objects = new ArrayList<>();
                objects.add(orders);
                // 不是额外订单，且是合并支付
                if (orders.getType().equals("0") && "merge".equals(sysTopUp.getOrderType())){
                    //根据定查询子订单
                    List<Orders> list=    ordersMapper.selectOrdersByParentOrderType(orders.getOrderId());
                    objects.addAll(list);
                }
                for (Orders orders1 : objects) {
                    orders1.setOrderStatus("6");
                    orders1.setPaymentTime(new Date());
                    ordersMapper.updateOrders(orders1);
                    try {
                        noticeController.sendMessage(orders1.getUserId() + "", "1", BusinessConstants.message_3);

                    }catch (Exception e){
                        log.error("支付回调发送消息失败", e);
                    }
                }
                // 修改支付
                sysTopUp.setStatus("3");
                sysTopUpService.updateSysTopUp(sysTopUp);
            }

            // 返回成功响应
            return AjaxResult.success("回调成功");
        } catch (Exception e) {
            // 记录错误日志
            log.error(e.getMessage(), e);
            throw new RuntimeException("处理失败");
        }
    }
}
